package icdecs.action;

import icdecs.action.form.RegisListActionForm;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.upload.FormFile;
import org.w3c.dom.Node;

public class RegisListAction extends Action {
	/**
	 * 
	 */
	private final static String SUCCESS = "success";

	/*
	 * name of properties of SOAP method
	 */
	/**
	 * Authentication-Info tag name
	 */
	public static final String AUTHENTICATION_INFO = "authenticationInfo";

	/**
	 * Authentication-ID tag name
	 */
	public static final String AUTHENTICATION_ID = "AuthenticationID";

	/**
	 * Authentication-Key tag name
	 */
	public static final String AUTHENTICATION_KEY = "AuthenticationKey";

	/**
	 * Organization-ID tag name
	 */
	public static final String ORGANIZATION_ID = "OrganizationID";

	/**
	 * Card-ID tag name
	 */
	public static final String CARD_ID = "CardID";

	/**
	 * Generated-time tag name
	 */
	public static final String GENERATED_TIME = "GeneratedTime";

	/**
	 * Number-of-cards tag name
	 */
	public static final String NUMBER_OF_CARDS = "Numberofcards";

	/**
	 * outdated-card-list tag name
	 */
	public static final String OUTDATED_CARD_LIST = "outdatedCardlist";

	/**
	 * icdecs namespace
	 */
	public static final String ICDECS_NAMESPACE = "icdecs";

	static final public DateFormat DateDBFormat = new SimpleDateFormat(
			"yyyy-MM-dd'T'HH:mm:ss");

	@Override
	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		// TODO Auto-generated method stub
		// RegisListActionForm regisListActionForm = new RegisListActionForm();
		String status = "";
		RegisListActionForm regisform = (RegisListActionForm) form;

		// get data from ActionForm
		String authenticationID = (String) regisform.get("authenticationID");
		String authenticationKey = (String) regisform.get("authenticationKey");
		String organizationID = (String) regisform.get("organizationID");
		String cardIDArray = (String) regisform.get("cardID");
		FormFile uploadFile = (FormFile) regisform.get("uploadFile");
		String mode = (String) regisform.get("mode");

		// Get list CardId from CSV file or input to textArea
		ArrayList<String> listCardID = new ArrayList<String>();
		if (mode.compareToIgnoreCase("csv") == 0) {
			listCardID = getDataFromCSVFile(uploadFile);
		} else {
			for (String cardid : cardIDArray.split("\r\n")) {
				listCardID.add(cardid);
			}
		}

		// Call function createSOAPRequest with values get from ActionForm
		SOAPMessage smsg = createSOAPRequest(authenticationID,
				authenticationKey, organizationID, listCardID);
		SOAPConnection conn = SOAPConnectionFactory.newInstance()
				.createConnection();
		SOAPMessage result = conn.call(smsg,
				"http://localhost:8080/icdecs/services/registList");
		Node nStatusCode = result.getSOAPPart()
				.getElementsByTagName("icdecs:StatusCode").item(0);
		Node nStatusMessage = result.getSOAPPart()
				.getElementsByTagName("icdecs:StatusMessage").item(0);

		nStatusCode.getTextContent();

		status = nStatusMessage.getTextContent();
		regisform.set("message", status);

		System.out.print("Response SOAP Message = ");
		result.writeTo(System.out);
		return mapping.findForward(SUCCESS);
	}

	/**
	 * This is function create SOAP envelop for registListRequest
	 * 
	 * @param authenticationID
	 * @param authenticationKey
	 * @param organizationID
	 * @param listCardID
	 * @return SOAPMessage
	 * @throws Exception
	 */
	private SOAPMessage createSOAPRequest(String authenticationID,
			String authenticationKey, String organizationID,
			ArrayList<String> listCardID) throws Exception {
		MessageFactory messageFactory = MessageFactory.newInstance();
		SOAPMessage soapMessage = messageFactory.createMessage();
		SOAPPart soapPart = soapMessage.getSOAPPart();

		String serverXSD = "http://www.w3.org/2001/XMLSchema";
		String serverXSI = "http://www.w3.org/2001/XMLSchema-instance";
		String serverIcdecs = "http://localhost:8080/icdecs/Schema";
		// SOAP Envelope
		SOAPEnvelope envelope = soapPart.getEnvelope();
		envelope.addNamespaceDeclaration("xsd", serverXSD);
		envelope.addNamespaceDeclaration("xsi", serverXSI);
		envelope.addNamespaceDeclaration(ICDECS_NAMESPACE, serverIcdecs);

		// SOAP Body
		SOAPBody soapBody = envelope.getBody();
		SOAPElement soapRegistListRequest = soapBody.addChildElement(
				"registListRequest", "icdecs");
		/**
		 * set authenticationInfo
		 */
		SOAPElement soapAuthenticationInfo = soapRegistListRequest
				.addChildElement(AUTHENTICATION_INFO, ICDECS_NAMESPACE);

		SOAPElement soapAuthenticationID = soapAuthenticationInfo
				.addChildElement(AUTHENTICATION_ID, ICDECS_NAMESPACE);
		soapAuthenticationID.addTextNode(authenticationID);
		SOAPElement soapAuthenticationKey = soapAuthenticationInfo
				.addChildElement(AUTHENTICATION_KEY, ICDECS_NAMESPACE);
		soapAuthenticationKey.addTextNode(authenticationKey);
		SOAPElement soapOrganizationID = soapAuthenticationInfo
				.addChildElement(ORGANIZATION_ID, ICDECS_NAMESPACE);
		soapOrganizationID.addTextNode(organizationID);

		/**
		 * set OutdatedCardlist
		 */
		SOAPElement soapOutdatedCardlist = soapRegistListRequest
				.addChildElement(OUTDATED_CARD_LIST, ICDECS_NAMESPACE);

		SOAPElement soapGeneratedTime = soapOutdatedCardlist.addChildElement(
				GENERATED_TIME, ICDECS_NAMESPACE);
		soapGeneratedTime.addTextNode(formatDateDBFormat(new Date()));
		SOAPElement soapNumberofcards = soapOutdatedCardlist.addChildElement(
				NUMBER_OF_CARDS, ICDECS_NAMESPACE);

		soapNumberofcards.addTextNode(String.valueOf(listCardID.size()));

		for (String carID : listCardID) {
			soapOutdatedCardlist.addChildElement(CARD_ID, ICDECS_NAMESPACE)
					.addTextNode(String.valueOf(carID));
		}

		MimeHeaders headers = soapMessage.getMimeHeaders();
		headers.addHeader("SOAPAction", "");

		soapMessage.saveChanges();

		/* Print the request message */
		System.out.print("Request SOAP Message = ");
		soapMessage.writeTo(System.out);
		System.out.println();

		return soapMessage;
	}

	public String formatDateDBFormat(Date date) {
		String formated;
		synchronized (DateDBFormat) {
			formated = DateDBFormat.format(date);
		}
		return formated;
	}

	/**
	 * Get list cardID form CSVfile
	 * 
	 * @param csvFile
	 * @return ArrayList<String> return ArrayList cardID
	 */
	public ArrayList<String> getDataFromCSVFile(FormFile csvFile) {

		BufferedReader br = null;
		String line = "";
		ArrayList<String> finalCardID = new ArrayList<String>();
		try {
			br = new BufferedReader(new InputStreamReader(
					csvFile.getInputStream()));
			while ((line = br.readLine()) != null) {
				if (line.compareToIgnoreCase("") != 0) {
					finalCardID.add(line);
				}
			}

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return finalCardID;
	}

}
